package com.woniuxy.qiantai.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.dal.entity.Userinfo;
import com.woniuxy.qiantai.model.Result;
import com.woniuxy.servicelayer.UserinfoService;
import com.woniuxy.servicelayer.util.JwtUtil;
import com.woniuxy.servicelayer.util.Md5Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * 用户表(Userinfo)表控制层
 *
 * @author makejava
 * @since 2023-03-27 22:21:38
 */
@RestController
@RequestMapping("userinfo")
@Slf4j
public class UserinfoController {
    /**
     * 服务对象
     */
    @Resource
    private UserinfoService userinfoService;
    @Autowired
    RedisTemplate<String, String> stringRedisTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Value("${SavePath.ProfilePhoto}")
    private String ProfilePhotoSavePath;   //图片物理存储路径
    @Value("${SavePath.ProfilePhotoMapper}")
    private String ProfilePhotoMapperPath;   //图片映射路径

    /**
     * 換綁手機號
     * @param map
     * @param request
     * @return
     */
    @PostMapping("updateUserPhoneNumber")
    public Result<String>updateUserPhoneNumber(@RequestBody Map<String,Object> map , HttpServletRequest request){
       //從前端拿到手機號和驗證碼
        String phoneNumber = (String) map.get("phoneNumber");
        String repass = (String) map.get("repass");
        //拿到token
        String token = request.getHeader("token");
        System.out.println(token);
        Object userId = JwtUtil.parseValue(request.getHeader("token"), "userId");
        System.out.println(userId);
        //去數據庫裡查詢是否有重複的手機號
        Userinfo userByAccount = userinfoService.getUserByAccount(phoneNumber);
        //获取验证码
        String code = stringRedisTemplate.opsForValue().get(phoneNumber);
        if (!repass.equals(code)) {
            return Result.failResult("验证码错误,请重新输入");
        }
        if (userByAccount != null) {
            return Result.registeredFailResult("手机号已注册过");
        }
        if ("okk".equals(getCode(phoneNumber).getMsg())) {
            return getCode(phoneNumber);
        }
        Integer res =userinfoService.updateUserPhoneNumber(phoneNumber, (Integer) userId);
        if (res==1)return Result.successResult("success");
        return Result.failResult("fail");
    }

    /**
     * 修改用戶密碼
     * @param param
     * @param request
     * @return
     */
        @PostMapping("updateUserPass")
    public Result<String>updateUserPass(@RequestBody Map<String,Object> param , HttpServletRequest request){
        System.out.println(param);
        String token = request.getHeader("token");
        System.out.println(token);
        String newUserPass = (String) param.get("config1");
        String checkNewUserPass = (String) param.get("config2");
        if (!Objects.equals(newUserPass, checkNewUserPass))return Result.failResult("兩次密碼不一致錯誤");
        System.out.println(newUserPass);
        Object userId = JwtUtil.parseValue(request.getHeader("token"), "userId");
        String code = Md5Util.encode(newUserPass);
        Integer res = userinfoService.updateUserPassById(userId,code);
        System.out.println(res);
        return Result.successResult("success");
    }

    /**
     * 修改用戶名
     * @param param
     * @param request
     * @return
     */
    @PostMapping("updateUserName")
    public Result<String> updateUserName(@RequestBody Map<String,Object> param, HttpServletRequest request){
        System.out.println(param);
        String newUserName = (String) param.get("param");
        String token = request.getHeader("token");

//        System.out.println(token);
//        System.out.println(newUserName);

        if (param.get("param")==null)return Result.failResult("服務器錯誤");
        Object userId = JwtUtil.parseValue(request.getHeader("token"), "userId");

        Integer res = userinfoService.updateUserNameById(userId,newUserName.replaceAll("\\s*",""));
        System.out.println(res);
        return Result.successResult("success");
    }


    /**
     * 解析token
     */
    @PostMapping("analysis")
    public Result<Map<String, Object>> analysis(@RequestBody Map<String,String> param) {
        String code = (String) param.get("token");
        System.out.println(code);
        Map<String, Object> afterAnalysisMap = new HashMap<>();
//        String code = request.getHeader("token");
        Object userId = JwtUtil.parseValue(code, "userId");
        System.out.println(userId);
        Object username = JwtUtil.parseValue(code, "username");
        Object password = JwtUtil.parseValue(code, "password");
        Object phoneNumber = JwtUtil.parseValue(code, "phoneNumber");
        Object userIcon = JwtUtil.parseValue(code, "userIcon");
        Object permission = JwtUtil.parseValue(code, "permission");
        Object rangeScore = JwtUtil.parseValue(code, "rangeScore");
        afterAnalysisMap.put("userId", userId);
        afterAnalysisMap.put("username", username);
        afterAnalysisMap.put("password", password);
        afterAnalysisMap.put("phoneNumber", phoneNumber);
        afterAnalysisMap.put("userIcon", userIcon);
        afterAnalysisMap.put("permission", permission);
        afterAnalysisMap.put("rangeScore", rangeScore);


        System.out.println("CurrentUserName---------------------" + username);
        System.out.println("afterAnalysisMap---------------------" + afterAnalysisMap);
        System.out.println(afterAnalysisMap);
        return Result.successResult(afterAnalysisMap);
    }

    /**
     * 头像上传
     *
     * @param fileUpload 图片资源
     * @return 图映射的虚拟访问路径
     */
    @PostMapping("profilePhotoUpload")
    public Result profilePhotoUpload(@RequestParam("file") MultipartFile fileUpload, String token, HttpServletRequest request) {
        System.out.println(token);
        System.out.println("///////开始上传文件////////");
        //获取文件名
        String fileName = fileUpload.getOriginalFilename();
        System.out.println(fileName);
        //获取文件后缀名。也可以在这里添加判断语句，规定特定格式的图片才能上传，否则拒绝保存。
        String suffix = fileName.substring(fileName.length()-3);
        System.out.println(suffix);
        if (suffix.equals("jpg")||suffix.equals("png")||suffix.equals("jpeg")){

        if (fileName == null || fileName.equals("")) {return Result.failResult("非法文件名");}
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //为了避免发生图片替换，这里使用了文件名重新生成
        fileName = UUID.randomUUID() + suffixName;
        try {
            //将图片保存到文件夹里
            fileUpload.transferTo(new File(ProfilePhotoSavePath + fileName));
            String photoName = ProfilePhotoMapperPath + fileName;
            System.out.println(photoName);
            System.out.println("///////文件上传完成////////");
            // 修改文件在數據庫里的url
//            System.out.println(substring);
            String phoneNumber = JwtUtil.parseValueWithoutException(token, "phoneNumber");
            System.out.println("phoneNumber*****************" + phoneNumber);
            int code = userinfoService.modifyImgsURL(phoneNumber, photoName);
            //上傳成功
            if (code == 1) return Result.successResult(photoName);

            //上傳失敗則刪除剛才上傳的圖片
            new File(ProfilePhotoSavePath + fileName).delete();
            return Result.failResult(photoName);

        } catch (Exception e) {

            return Result.failResult("系統錯誤");
        }

        }else {
            return Result.failResult("圖片格式不符合");
        }

    }

    /**
     * 手機密碼登錄
     *
     * @return
     */
    @CrossOrigin
    @PostMapping("login")
    public Result login(@RequestBody Map<String, Object> map) {
        Result result = new Result<>();

        String username = (String) map.get("username");
        String password = (String) map.get("password");

        System.out.println(username);
        System.out.println(password);

        String code = Md5Util.encode(password);
        System.out.println("code============" + code);

        //這個username其實是用戶輸入的電話號碼,也就是賬號
        //將用戶輸入的原始密碼md5加密後送入數據庫進行查找
        Userinfo userinfo = userinfoService.checkLogin(username, Md5Util.encode(password));
        System.out.println(userinfo);

        if (userinfo == null) {
            return Result.failResult("手机号或密码错误");
        } else {

//            String userToken = JwtUtil.createTokenSingleInfo(24 * 60, "username", userinfo.getPhoneNumber());
            //將用戶信息放入map

            // 将加密过的密码从新放入对象
            userinfo.setPassword(code);
            Map<String, Object> userinfoMap = objectPutMap(userinfo);
            System.out.println(userinfoMap);
            System.out.println("-----------------------------------");
            System.out.println("-----------------------------------");
            System.out.println("-----------------------------------");
            System.out.println("-----------------------------------");
            System.out.println("-----------------------------------");
            System.out.println(  userinfoMap.get("userId"));
            System.out.println(  userinfoMap.get("permission"));
            System.out.println(  userinfoMap.get("rangeScore"));
            String userToken = JwtUtil.createToken(24 * 60, userinfoMap);
            System.out.println(userToken);

            result = Result.successResult(userToken);
        }

        //把用戶輸入的密碼加密後和數據庫裡在註冊時加密過的密文進行比較,比對失敗則發送錯誤信息
        if (!userinfo.getPassword().equalsIgnoreCase(Md5Util.encode(password))) {
            return Result.failResult("用户名或密码错误");
        }
        return result;
    }

    /**
     * 将对象放入map
     */
    public Map<String, Object> objectPutMap(Userinfo userinfo) {
        Map<String, Object> userinfoMap = new HashMap<>();
        userinfoMap.put("userId", userinfo.getUserId());
        userinfoMap.put("username", userinfo.getUsername());
        userinfoMap.put("password", userinfo.getPassword());
        userinfoMap.put("phoneNumber", userinfo.getPhoneNumber());
        userinfoMap.put("userIcon", userinfo.getUserIcon());
        userinfoMap.put("permission", userinfo.getPermission());
        userinfoMap.put("rangeScore", userinfo.getRangeScore());
        return userinfoMap;
    }


    /**
     * 獲取當前用戶名
     *
     * @param token 令牌
     * @return
     */
    @CrossOrigin
    @RequestMapping("getCurrentUserName")
    public Result<String> getCurrentUserName(String token, HttpServletRequest request) {

        //解析token
        String username = JwtUtil.parseValueWithoutException(token, "username");
        System.out.println("CurrentUserName" + username);
        request.getSession().setAttribute("userToken", username);
        return Result.successResult(username);
    }

    /**
     * 修改用户信息
     *
     * @return
     */
    @RequestMapping("updateUserInfo")
    public int updateUserInfo(Userinfo userinfo) {
        return userinfoService.updateUserInfo(userinfo);
    }

    /**
     * 查询用户信息 返回分页结果
     */
    @RequestMapping("selectUserInfo")
    public Page<Userinfo> selectUserInfo(Integer currentPage, Integer pageSize, String keyword) {
        return userinfoService.selectUserInfo(currentPage, pageSize, keyword);
    }

    /**
     * 添加用户
     *
     * @param userinfo
     * @return
     */
    @RequestMapping("addUser")
    public int addUser(@RequestBody Userinfo userinfo) {
        Userinfo userinfo1 = new Userinfo();
        userinfo1.setUserId(userinfo.getUserId());
        userinfo1.setUsername(userinfo.getUsername());
        //密码加密
        String encode = Md5Util.encode(userinfo.getPassword());
        userinfo1.setPassword(encode);
        userinfo1.setPhoneNumber(userinfo.getPhoneNumber());
        userinfo1.setUserIcon(userinfo.getUserIcon());
        //新增用户默认用户为学生
        userinfo1.setPermission(2);
        //默认靶场总分为零
        userinfo1.setRangeScore(0);
        int addUser = userinfoService.addUser(userinfo1);
        return addUser;
    }

    /**
     * 根据id删除用用户
     *
     * @param
     * @return
     */
    @RequestMapping("deleteUser")
    public int deleteUser(Integer userId) {
        int deleteUser = userinfoService.deleteUser(userId);
        return deleteUser;
    }

    /**
     * 重置密码 默认为123456
     *
     * @param userId
     * @param
     * @return
     */
    @RequestMapping("resetPassword")
    public String resetPassword(Integer userId) {
        String password = userinfoService.resetPassword(userId);
        Userinfo userinfo = userinfoService.selectUserById(userId);
        Map<String,String> map = new HashMap<>();
        map.put("phoneNumber",userinfo.getPhoneNumber());
        map.put("password",password);
        rabbitTemplate.convertAndSend("directExchange","password",map);

        return "okk";
    }


    /**
     * 根据用户id修改角色
     *
     * @param userId
     * @param permission
     * @return
     */
    @RequestMapping("personalize")
    public String personalize(Integer userId, Integer permission) {
        int personalize = userinfoService.personalize(userId, permission);
        if (personalize != 0) {
            return "ok";
        }
        return "赋予角色失败";
    }

    /**
     * 根据用户id查询出当前的用户的角色
     *
     * @param userId
     * @return
     */
    @RequestMapping("getThisRole")
    public Userinfo getThisRole(Integer userId) {
        return userinfoService.getThisRole(userId);
    }

    /**
     * 修改密码前获取原有密码
     *
     * @param userId
     * @param password
     * @return
     */
    @RequestMapping("oldPassword")
    public String oldPassword(Integer userId, String password) {
        return userinfoService.oldPassword(userId, password);
    }


    /**
     * 获取验证码
     */
    //todo 加@注解报错
    @RequestMapping("getCode")
    public Result<String> getCode(String phoneNumber) {

        //判断手机号是否合法
        String format = "^1[3-9]\\d{9}$";
        if (phoneNumber == null || !phoneNumber.matches(format)) {
            return Result.failResult("手机号非法");
        }

        if (StringUtils.isEmpty(phoneNumber)) {
            return Result.failResult("手机号不能为空");
        }

        String code = stringRedisTemplate.opsForValue().get(phoneNumber);
        if (StringUtils.isEmpty(code)) {
            rabbitTemplate.convertAndSend("directExchange","code",phoneNumber);
        }

        return Result.successResult("okk");
    }

    /**
     * 注册
     */
    @RequestMapping("register")
    public Result<String> register(@RequestBody Map<String, Object> map) throws Exception {
        //查询数据库是否存在手机号
        String phoneNumber = (String) map.get("phoneNumber");
        String repass = (String) map.get("repass");
        Userinfo userByAccount = userinfoService.getUserByAccount(phoneNumber);

        //获取验证码
        String code = stringRedisTemplate.opsForValue().get(phoneNumber);

        if (!repass.equals(code)) {
            return Result.failResult("验证码错误,请重新输入");
        }

        if (userByAccount != null) {
            return Result.registeredFailResult("手机号已注册过，正在为您转跳登录页");
        }
        if ("okk".equals(getCode(phoneNumber).getMsg())) {
            return getCode(phoneNumber);
        }

        //蜗牛_手机号后4位
        String substring = phoneNumber.substring(7, 11);

        //Wn+四位随机数字+手机号后四位。
        String password = "Wn" + (int) ((Math.random() * 9 + 1) * 1000) + substring;

        //密码加密
        String codes = Md5Util.encode(password);


        Userinfo newUserinfo = new Userinfo(null, "蜗牛_" + substring, codes, phoneNumber, null, 2, 0);

        userinfoService.save(newUserinfo);
        stringRedisTemplate.delete(phoneNumber);
        Map<String,String> userMap = new HashMap<>();
        userMap.put("phoneNumber",phoneNumber);
        userMap.put("password",password);
        rabbitTemplate.convertAndSend("directExchange","user",userMap);
        return Result.successResult("okk");
    }

    /**
     * 注册存token
     */
    @PostMapping("registerReleaseToken")
    public Result<String> registerReleaseToken(String phoneNumber) {
        Userinfo userinfo = userinfoService.phoneNumberToUser(phoneNumber);
        userinfo.setPassword(Md5Util.encode(userinfo.getPassword()));
        Map<String, Object> map = objectPutMap(userinfo);
        String token = JwtUtil.createToken(24 * 60, map);
        stringRedisTemplate.delete(phoneNumber);
        return Result.successResult(token);
    }

    /**
     * 获取权限
     */
    @PostMapping("getPermission")
    public Result<Integer> getPermission(String token){
        Integer permission = (Integer)JwtUtil.parseValue(token,"permission");
        System.out.println(permission);
        return Result.successResult(permission);
    }
}

